using Microsoft.Xna.Framework;
using System;
using System.Xml;
namespace HMCollada.FX {
    internal interface HMColladaValueType { }

    internal struct HMColladaBool : HMColladaValueType {
        internal bool value;
        internal HMColladaBool(bool newValue) { value = newValue; }
    }
    internal struct HMColladaBool2 : HMColladaValueType {
        internal bool[] value;
        internal HMColladaBool2(bool[] newValue) { value = newValue; }
    }
    internal struct HMColladaBool3 : HMColladaValueType {
        internal bool[] value;
        internal HMColladaBool3(bool[] newValue) { value = newValue; }
    }
    internal struct HMColladaBool4 : HMColladaValueType {
        internal bool[] value;
        internal HMColladaBool4(bool[] newValue) { value = newValue; }
    }
    internal struct HMColladaInt : HMColladaValueType {
        internal int value;
        internal HMColladaInt(int newValue) { value = newValue; }
    }
    internal struct HMColladaInt2 : HMColladaValueType {
        internal int[] value;
        internal HMColladaInt2(int[] newValue) { value = newValue; }
    }
    internal struct HMColladaInt3 : HMColladaValueType {
        internal int[] value;
        internal HMColladaInt3(int[] newValue) { value = newValue; }
    }
    internal struct HMColladaInt4 : HMColladaValueType {
        internal int[] value;
        internal HMColladaInt4(int[] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat : HMColladaValueType {
        internal float value;
        internal HMColladaFloat(float newValue) { value = newValue; }
    }
    internal struct HMColladaFloat2 : HMColladaValueType {
        internal float[] value;
        internal HMColladaFloat2(float[] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat3 : HMColladaValueType {
        internal float[] value;
        internal HMColladaFloat3(float[] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat4 : HMColladaValueType {
        internal float[] value;
        internal HMColladaFloat4(float[] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat1x1 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat1x1(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat1x2 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat1x2(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat1x3 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat1x3(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat1x4 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat1x4(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat2x1 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat2x1(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat2x2 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat2x2(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat2x3 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat2x3(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat2x4 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat2x4(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat3x1 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat3x1(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat3x2 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat3x2(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat3x3 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat3x3(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat3x4 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat3x4(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat4x1 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat4x1(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat4x2 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat4x2(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat4x3 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat4x3(float[][] newValue) { value = newValue; }
    }
    internal struct HMColladaFloat4x4 : HMColladaValueType {
        internal float[][] value;
        internal HMColladaFloat4x4(float[][] newValue) { value = newValue; }
    }
}

namespace HMCollada {
    internal partial class HMColladaLoader {
        private static string ReadString() {
            return colladaReader.ReadElementContentAsString();
        }

        private static float[] ReadGenericFloatArray(int n) {
            do { colladaReader.Read(); } while (colladaReader.NodeType != XmlNodeType.Text);

            float[] final = new float[n];
            string content = colladaReader.Value.Trim();
            string[] values = content.Split(new string[] { "  ", " " }, n, StringSplitOptions.None);

            for (int i = 0; i < n; i++) final[i] = float.Parse(values[i]);
            return final;
        }

        private static float ReadFloat() {
            do { colladaReader.Read(); } while (colladaReader.Name != "float");

            return colladaReader.ReadElementContentAsFloat();
        }

        private static float[] ReadFloat(int n) {
            return ReadGenericFloatArray(n);
        }

        private static float[][] ReadFloat(int n, int m) {
            do { colladaReader.Read(); } while (colladaReader.Name != "float");

            float[][] final = new float[n][];
            string content = colladaReader.ReadElementContentAsString().Trim();
            string[] values = content.Split(new char[] { ' ' }, n * m);

            for (int i = 0; i < n; i++) {
                final[i] = new float[m];

                for (int j = 0; j < m; j++) {
                    final[i][j] = float.Parse(values[i * n + j]);
                }
            }

            return final;
        }

        private static bool ReadBool() {
            do { colladaReader.Read(); } while (colladaReader.Name != "bool");

            return colladaReader.ReadElementContentAsBoolean();
        }

        private static bool[] ReadBool(int n) {
            do { colladaReader.Read(); } while (colladaReader.Name != "bool");

            bool[] final = new bool[n];
            string content = colladaReader.ReadElementContentAsString().Trim();
            string[] values = content.Split(new char[] { ' ' }, n);

            for (int i = 0; i < n; i++) final[i] = bool.Parse(values[i]);
            return final;
        }

        private static Vector4 ReadColor() {
            do { colladaReader.Read(); } while (colladaReader.Name != "color");
            string content = colladaReader.ReadElementContentAsString().Trim();
            string[] values = content.Split(new char[] { ' ' }, 4);

            return new Vector4(
                float.Parse(values[0]),
                float.Parse(values[1]),
                float.Parse(values[2]),
                float.Parse(values[3])
            );
        }
    }
}